#include "stdafx.h"
/*
enum abil_state { casting, cooldown, travel, dot };
struct timer_state
{
    abil_state state;
	float delay; // either cooldown or cast time
	unsigned short emit, abil, target;
};
timers
float cooltime;
unsigned char mask, range, radius, velocity, ticks, cost;
abilbases
unsigned short dmg, dmg_tick, dmg_per_level, dmg_tick_per_level;
abilchar
unsigned short experience, id, dmg, dmg_tick;
*/
void game_machine :: cast_command(ushort emit, ushort abil, ushort target)
{
    ushort abid = Characters[emit].Abilities[abil].abil;
	// check range, obstacle, mana, cooldown
	if(Characters[emit].Abilities[abil].on_cooldown)
        { error_message(is_on_cooldown);  return; }
    if(Characters[emit].power < AbilBases[abid].cost)
        { error_message(out_of_mana); return; }
    /* lacks range and obstacle, will require raycast and scenequeries */
    
    if(availables.empty())
        Timers.push_back(timer_state());

    Timers[availables.back()].abil = abil;
    Timers[availables.back()].emit = emit;
    Timers[availables.back()].target = target;

    if(AbilBases[abid].cooltime <= 0.0f) // cd
    {
        Timers[availables.back()].delay = - AbilBases[abid].cooltime;
        Timers[availables.back()].state = cooldown;
        Characters[emit].Abilities[abil].on_cooldown = 1;
    }
    else // charge
    {
        Timers[availables.back()].delay = AbilBases[abid].cooltime;
        Timers[availables.back()].state = casting;
    }

    if(! availables.empty())
        availables.pop();
}
void game_machine :: cast_start(ushort emit, ushort abil, ushort target)
{

}
void game_machine :: cast_land(ushort emit, ushort abil, ushort target)
{

}
void game_machine :: pass()
{
	//size_t sz = Timers.size();
	//for(size_t i = 0; i < sz; ++ i)
	for(auto i = Timers.begin(); i < Timers.end(); ++ i)
	{
		switch(i->state)
		{
		// here the player decided to cast a spell and pushed the key
		case casting:
            i->delay -= timeSinceLastFrame;
            if (i->delay < 0.f)
            {
                if(AbilBases[Characters[i->emit].Abilities[i->abil].abil].velocity == 0)
                    apply_effect(i->emit, i->target, i->abil);
                else ; // launch a missile
                availables.push(std::distance(Timers.begin(), i)); // mark timers as replaceable
            }
			break;
		// here the spell is cast
		case cooldown:
            i->delay -= timeSinceLastFrame;
            if (i->delay < 0.f)
            {
                Characters[i->emit].Abilities[i->abil].on_cooldown = 0; // no more on cooldown
                availables.push(std::distance(Timers.begin(), i)); // mark timers as replaceable
            }
			break;
		// nothing here
		case travel:
			break;
		// here the spell lands
		case dot:

			break;
		}
	}
}
void game_machine :: error_message(err_msg m)
{
    switch(m)
    {
        case out_of_mana:
            LOGMSG("Not enough of mana !");
            break;
        case obstacle:
            LOGMSG("Can't see the target !");
            break;
        case too_far_away:
            LOGMSG("Too far away !");
            break;
        case is_on_cooldown:
            LOGMSG("Can't do that yet !");
            break;
    }
}
